package cc.rengu.redp.flowable.delegate;

import cc.rengu.redp.common.utils.SpringContextUtil;
import cc.rengu.redp.flowable.domain.CustomServiceNode;
import cc.rengu.redp.flowable.domain.FlowData;
import cc.rengu.redp.flowable.service.FlowDataService;
import cc.rengu.redp.flowable.service.impl.BizWorkFlowVar;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;

/**
 *
 * 流程后台任务基础类
 *
 * 说明：
 * 流程后台任务基础类，所有后台服务需在此类基础上扩展，参考TestDelegate
 * 由于工作流引擎配置采用spring bean的形式加载类，故所有继承自此类的类需要添加@Service注解
 * 所有BaseDelegate的衍生类会被自动注册
 */
@Slf4j
public abstract class BaseDelegate implements JavaDelegate {

    @Override
    public void execute(DelegateExecution execution) {
        CustomServiceNode customServiceNode = JSON.parseObject(execution.getCurrentFlowElement().getDocumentation(), CustomServiceNode.class);
        FlowDataService flowDataService = SpringContextUtil.getBean(FlowDataService.class);
        BizWorkFlowVar bizWorkflowVar = new BizWorkFlowVar();

        FlowData flowData = flowDataService.getFlowData(execution.getProcessInstanceId());
        if (flowData == null) {
            //空再从变量里拿，减少读表次数
            BizWorkFlowVar currVar = new BizWorkFlowVar(execution.getVariables());
            flowData = flowDataService.getById(Long.valueOf(currVar.getFlowDataId()));
        }
        JSONObject origFlowDataObj = JSON.parseObject(flowData.getFlowData());

        try {
            //复制一份数据，防止doExecute直接返回参数造成下面两对象比较不正确
            JSONObject newFlowDataObj = doExecute((JSONObject) origFlowDataObj.clone());
            if (!newFlowDataObj.equals(origFlowDataObj)) {
                //保存自动处理的数据
                flowData.setFlowData(newFlowDataObj.toJSONString());
                flowDataService.modifiedFlowData(flowData);
            }
        } catch (Exception e) {
            if (e instanceof DelegateExceptionButSaveData) {
                JSONObject newFlowDataObj = ((DelegateExceptionButSaveData) e).getSaveData();
                if (!newFlowDataObj.equals(origFlowDataObj)) {
                    //保存自动处理的数据
                    flowData.setFlowData(newFlowDataObj.toJSONString());
                    flowDataService.modifiedFlowData(flowData);
                }
            }

            log.error("Service Task run down in error.", e.getMessage());
            bizWorkflowVar.setFlowStatus(customServiceNode.getPerformFailOutgoingId());
        }

        // 空即执行成功
        if (StringUtils.isBlank(bizWorkflowVar.getFlowStatus())) {
            bizWorkflowVar.setFlowStatus(customServiceNode.getPerformSuccessOutgoingId());
        }

        execution.setVariables(bizWorkflowVar.getVarMap());
    }

    /**
     * delegate 执行方法
     * @param jsonObject
     * @return
     * @throws Exception
     */
    abstract public JSONObject doExecute(JSONObject jsonObject) throws Exception;

    /**
     * delegate 在配置时的选项描述
     * @return
     */
    abstract public String delegateSimpleDescription();
}
